package com.demarc.pesquisas.negocio.util;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;

import javax.faces.context.FacesContext;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;

import com.demarc.pesquisas.negocio.entidade.DiaSemanaEnum;

public class DateUtils {

    public static final Locale LOCALE_PT_BR = new Locale("pt", "br");
    public static final String DATA_PADRAO_COM_HORA = "dd-MM-yyyy-HHmm";
    public static final String DATA_PADRAO_PT_BR_COM_TRACO = "dd-MM-yyyy";
    public static final String DATA_PADRAO_PT_BR = "dd/MM/yyyy";
    public static final String DATA_PADRAO_EN_US = "MM/dd/yyyy";
    public static final String PADRAO_ANO = "yyyy";
    public static final String ANO = " ano";
    public static final String ANOS = " anos";
    public static final String MES = " mês ";
    public static final String MESES = " meses";
    public static final String E = " e ";
    public static final String HORA_PADRAO_HH_MM = "HH:mm";
    public static final String HORA_PADRAO_HH_MM_SS = "HH:mm:ss";
    public static final String BARRA = "/";
    public static final String TRACO = "-";
    public static final String COMPLEMENTO_AS = " ás ";

    public static LocalDate converterStringParaLocalDate(String valor, String padraoData) {

        LocalDate data = null;
        if (StringUtils.isNotBlank(valor)) {
            DateTimeFormatter formatador = getFormatadorData(padraoData);
            data = formatador.parseDateTime(valor.trim()).toLocalDate();
        }
        return data;
    }

    public static String getPadraoData(Locale locale) {
        String pattern = DATA_PADRAO_EN_US;

        if (LOCALE_PT_BR.getLanguage().equalsIgnoreCase(locale.getLanguage())) {
            pattern = DATA_PADRAO_PT_BR;
        }

        return pattern;
    }

    public static String getPadraoData() {
        Locale locale = LOCALE_PT_BR;

        FacesContext context = FacesContext.getCurrentInstance();
        if (context != null) {
            locale = context.getViewRoot().getLocale();
        }

        return getPadraoData(locale);
    }

    public static String converterLocalDateParaString(LocalDate valor, String padraoData) {
        String dataString = null;
        if (valor != null) {
            DateTimeFormatter formatador = getFormatadorData(padraoData);
            dataString = valor.toString(formatador);
        }
        return dataString;
    }

    public static String converterDateTimeParaString(DateTime valor, String padraoData) {
        String dataString = null;
        if (valor != null) {
            DateTimeFormatter formatador = getFormatadorData(padraoData);
            dataString = valor.toString(formatador);
        }
        return dataString;
    }

    public static String converterDateTimeParaString(LocalDate valor, String padraoData) {
        String dataString = null;
        if (valor != null) {
            DateTimeFormatter formatador = getFormatadorData(padraoData);
            dataString = valor.toString(formatador);
        }
        return dataString;
    }

    public static String converterDateParaString(Date data, String padraoData) {
        String dataString = null;
        if (data != null) {
            SimpleDateFormat formatador = new SimpleDateFormat(padraoData);
            dataString = formatador.format(data);
        }
        return dataString;
    }

    private static DateTimeFormatter getFormatadorData(String padraoData) {
        return new DateTimeFormatterBuilder().appendPattern(padraoData).toFormatter()
                .withLocale(LOCALE_PT_BR);
    }

    public static boolean isDataComPadraoDDMMAAA(String data) {
        Pattern padrao = Pattern.compile("^\\d{2}/\\d{2}/\\d{4}$");
        return padrao.matcher(data).matches();
    }

    /**
     * Avaliar se a data é um sábado ou domingo.
     * 
     * @param data Data a ser avaliada.
     * 
     * @return true se o dia for um sábado ou domingo, false para os outros dias da semana.
     */
    public static boolean isFimDeSemana(LocalDate data) {
        List<Integer> finaisSemana =
                Arrays.asList(DateTimeConstants.SATURDAY, DateTimeConstants.SUNDAY);

        return finaisSemana.contains(data.getDayOfWeek());
    }

    public static boolean isDiaSemanaValido(LocalDate data,
            List<DiaSemanaEnum> listaDiasSemanaDisciplinaDiario) {

        boolean isDiaSemanaValido = false;
        for (DiaSemanaEnum diaSemanaEnum : listaDiasSemanaDisciplinaDiario) {
            if (DiaSemanaEnum.obterDiaPor(data.dayOfWeek().get()).getCodigo()
                    .equalsIgnoreCase(diaSemanaEnum.getCodigo())) {

                isDiaSemanaValido = true;
                break;
            }
        }
        return isDiaSemanaValido;
    }

    /**
     * Obtém o último dia de um mes a partir de uma data.
     * 
     * @param dataMes - Data que a partir dela será verificada a última data do mês.
     */
    public static LocalDate obterUltimoDiaMes(LocalDate dataMes) {
        return dataMes.dayOfMonth().withMaximumValue();
    }

    /**
     * Retorna o ano atual.
     * 
     * @return o ano atual.
     */
    public static String obterAnoAtual() {
        return obterDataAtual().toString(PADRAO_ANO);
    }

    public static String replaceTracoPorBarra(DateTime date) {
        return date == null ? StringUtils.EMPTY : date.toString(DATA_PADRAO_PT_BR_COM_TRACO)
                .replace(TRACO, BARRA);
    }

    public static String replaceTracoPorBarra(LocalDate date) {
        return date == null ? StringUtils.EMPTY : date.toString(DATA_PADRAO_PT_BR_COM_TRACO)
                .replace(TRACO, BARRA);
    }

    public static String obterHora(DateTime date) {
        return date == null ? StringUtils.EMPTY : date.toString(HORA_PADRAO_HH_MM);
    }

    /**
     * Retorna o ano atual.
     * 
     * @return o ano atual.
     */
    public static LocalDate obterDataAtual() {
        return obterDataHoraAtual().toLocalDate();
    }

    public static DateTime obterDataHoraAtual() {
        return DateTime.now();
    }
}
